const tokenKey = "user_token";
const fileTokenKey = "file_user_token";

/**
 * 闪烁某元素边框
 * elem：可接收id或者元素本身
 */
function flashRed(elem) {
    var elem = typeof elem === 'string' ? document.getElementById(elem) : elem;
    var oldBorderColor = elem.style.borderColor
    elem.style.borderColor = oldBorderColor == 'red' ? elem.borderColor : 'red'; //颜色默认为red
    if (!elem.timer) {//初始化timer属性
        elem.times = 5
        elem.borderColor = oldBorderColor // 保存元素原来的边框颜色
        elem.timer = setInterval(function () {
            flashRed(elem) //递归
        }, 180)
    } else {
        if (elem.times == 0) {
            clearInterval(elem.timer)
            elem.timer = null
            elem.style.borderColor = oldBorderColor //恢复为元素原来的边框颜色
        }
        elem.times--
    }
}

/**
 * 获取RSA公钥
 */
let getPublicKey = () => {
    // console.info('start getpublickey')
    return new Promise((resolve, reject) => {
        $.ajax({
            url: "http://localhost:8080/demo/getPublicKey?t=" + Math.floor(Math.random() * 100),
            type: "GET",
            dataType: 'json',
            crossDomain: true == !(document.all),
            success: result => {
                resolve(result);
            },
            error: err => {
                reject(err);
            }
        })
    })
}

/**
 * 获取cookie指定属性值
 **/
function getCookie(name) {
    var arr, reg = new RegExp("(^|)" + name + "=([^;]*)(;|$)");
    if (arr = document.cookie.match(reg)) {
        return decodeURIComponent(arr[2]);
    } else {
        return null
    }
}

/**
 * 删除,清空cookie
 **/
function delCookie(name) {
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    document.cookie = name + "=;expires=" + exp.toGMTString() + ";path=/";
}

/**
 * 设置token
 **/
function setToken(key, token) {
    var Days = 7;
    var exp = new Date();
    exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
    document.cookie = key + "=" + token + ";expires=" + exp.toGMTString() + ";path=/";
}

/**
 * 虚拟form提交请求(导出、下载、后台打印)
 * @param url 请求地址(带查询参数)
 * @param isNewPage 是否新页面打开
 * @param method 请求方式
 */
function formExport(url, isNewPage, method) {
    if (url) {
        let form = document.createElement('form');
        form.action = url;
        form.method = method || 'post';
        if (isNewPage) {
            form.target = '_blank';
        }
        //文件导出时需增加参数fileUserToken
        let input = document.createElement('input');
        input.type = "hidden";
        input.name = fileTokenKey;
        input.value = getCookie(tokenKey);
        form.appendChild(input);

        //是get请求，并且url含有参数
        if ("get" === form.method.toLowerCase() && url.indexOf("?") !== -1) {
            let params = url.split("?")[1];
            let param = params.split("&");
            for (let i = 0; i < param.length; i++) {
                let p = param[i].split("=");
                let input = document.createElement('input');
                input.type = "hidden";
                input.name = p[0];
                input.value = p[1];
                form.appendChild(input);
            }
        }
        document.body.appendChild(form);
        form.submit();
        form.remove();
    }
}



/**
 * Base64工具
 */
let Base64 = {
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    encode: function (e) {
        var t = "";
        var n, r, i, s, o, u, a;
        var f = 0;
        e = Base64._utf8_encode(e);
        while (f < e.length) {
            n = e.charCodeAt(f++);
            r = e.charCodeAt(f++);
            i = e.charCodeAt(f++);
            s = n >> 2;
            o = (n & 3) << 4 | r >> 4;
            u = (r & 15) << 2 | i >> 6;
            a = i & 63;
            if (isNaN(r)) {
                u = a = 64
            } else if (isNaN(i)) {
                a = 64
            }
            t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
        }
        return t
    },
    decode: function (e) {
        var t = "";
        var n, r, i;
        var s, o, u, a;
        var f = 0;
        e = e.replace(/[^A-Za-z0-9+/=]/g, "");
        while (f < e.length) {
            s = this._keyStr.indexOf(e.charAt(f++));
            o = this._keyStr.indexOf(e.charAt(f++));
            u = this._keyStr.indexOf(e.charAt(f++));
            a = this._keyStr.indexOf(e.charAt(f++));
            n = s << 2 | o >> 4;
            r = (o & 15) << 4 | u >> 2;
            i = (u & 3) << 6 | a;
            t = t + String.fromCharCode(n);
            if (u != 64) {
                t = t + String.fromCharCode(r)
            }
            if (a != 64) {
                t = t + String.fromCharCode(i)
            }
        }
        t = Base64._utf8_decode(t);
        return t
    },
    _utf8_encode: function (e) {
        e = e.replace(/rn/g, "n");
        var t = "";
        for (var n = 0; n < e.length; n++) {
            var r = e.charCodeAt(n);
            if (r < 128) {
                t += String.fromCharCode(r)
            } else if (r > 127 && r < 2048) {
                t += String.fromCharCode(r >> 6 | 192);
                t += String.fromCharCode(r & 63 | 128)
            } else {
                t += String.fromCharCode(r >> 12 | 224);
                t += String.fromCharCode(r >> 6 & 63 | 128);
                t += String.fromCharCode(r & 63 | 128)
            }
        }
        return t
    },
    _utf8_decode: function (e) {
        var t = "";
        var n = 0;
        var r = c1 = c2 = 0;
        while (n < e.length) {
            r = e.charCodeAt(n);
            if (r < 128) {
                t += String.fromCharCode(r);
                n++
            } else if (r > 191 && r < 224) {
                c2 = e.charCodeAt(n + 1);
                t += String.fromCharCode((r & 31) << 6 | c2 & 63);
                n += 2
            } else {
                c2 = e.charCodeAt(n + 1);
                c3 = e.charCodeAt(n + 2);
                t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
                n += 3
            }
        }
        return t
    }
}

/**
 * 日期处理工具类
 */
let DateUtil = {
    /**
     * 日期对象转换为指定格式的字符串
     * @param formatStr 日期格式,格式定义如下 yyyy-MM-dd HH:mm:ss
     * @param date Date 日期对象, 如果缺省，则为当前时间
     *
     * @return string 指定格式的时间字符串
     */
    dateToStr: function (formatStr, date) {
        date = arguments[1] || new Date();
        date = typeof date == "string" ? new Date(date.replace(/-/g, '/').replace(/T|Z/g, ' ').replace(/\.\d+/g, '').trim()) : (date - 0 == date - 0 ? new Date(date) : date);
        formatStr = arguments[0] || "yyyy-MM-dd HH:mm:ss";

        var str = formatStr;
        var Week = ['日', '一', '二', '三', '四', '五', '六'];
        str = str.replace(/yyyy|YYYY/, date.getFullYear());
        str = str.replace(/yy|YY/, (date.getYear() % 100) > 9 ? (date.getYear() % 100).toString() : '0' + (date.getYear() % 100));
        str = str.replace(/MM/, date.getMonth() >= 9 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1));
        str = str.replace(/M/g, date.getMonth());
        str = str.replace(/w|W/g, Week[date.getDay()]);

        str = str.replace(/dd|DD/, date.getDate() > 9 ? date.getDate().toString() : '0' + date.getDate());
        str = str.replace(/d|D/g, date.getDate());

        str = str.replace(/hh|HH/, date.getHours() > 9 ? date.getHours().toString() : '0' + date.getHours());
        str = str.replace(/h|H/g, date.getHours());
        str = str.replace(/mm/, date.getMinutes() > 9 ? date.getMinutes().toString() : '0' + date.getMinutes());
        str = str.replace(/m/g, date.getMinutes());

        str = str.replace(/ss|SS/, date.getSeconds() > 9 ? date.getSeconds().toString() : '0' + date.getSeconds());
        str = str.replace(/s|S/g, date.getSeconds());

        return str;
    },
    /**
     * 字符串转换为日期对象
     * @param date Date 格式为yyyy-MM-dd HH:mm:ss，必须按年月日时分秒的顺序，中间分隔符不限制
     */
    strToDate: function (dateStr) {
        var data = dateStr;
        var reCat = /(\d{1,4})/gm;
        var t = data.match(reCat);
        t[1] = t[1] - 1;
        eval('var d = new Date(' + t.join(',') + ');');
        return d;
    }
}

/**
 * 常用工具
 */
let Utils = {
    //table的searchForm表单数据，转换为url参数拼接形式
    urlEncodeByForm: function (isPagination, dataObj, dataForm, params) {
        var data = dataForm.serialize();
        if (!data) {
            data = Utils.urlEncodeByObj(dataObj);
        } else {
            data = data + "&" + Utils.urlEncodeByObj(dataObj);
        }
        //拼接分页参数
        if (isPagination && params != null && typeof (params) != "undefined") {
            if (typeof (params.sort) == "undefined") params.sort = "";
            var page = "pageSize=" + params.limit //页面条数
                + "&pageNum=" + params.offset //起始行数
                + "&orderBy=" + params.sort; //排序列名
            if (!data) {
                data = page;
            } else {
                data = data + "&" + page;
            }
        }
        return data;
    },
    /**
     *  将对象转换成url参数拼接
     * var obj={name:'tom','class':{className:'class1'},classMates:[{name:'lily'}]};
     * urlEncodeByObj(obj);
     * output: "name=tom&class.className=class1&classMates[0].name=lily"
     * urlEncodeByObj(obj,'stu');
     * output: "stu.name=tom&stu.class.className=class1&stu.classMates[0].name=lily"
     */
    urlEncodeByObj: function (param, key) {
        var paramStr = "";
        if (param instanceof String || param instanceof Number || param instanceof Boolean) {
            paramStr += "&" + key + "=" + encodeURIComponent(param);
        } else {
            $.each(param, function (i) {
                var k = key == null ? i : key + (param instanceof Array ? "[" + i + "]" : "." + i);
                paramStr += '&' + Utils.urlEncodeByObj(this, k);
            });
        }
        return paramStr.substr(1);
    },
    /**
     * 对象的深拷贝
     */
    deepClone:function (obj) {
        return JSON.parse(JSON.stringify(obj));
    },

}


/**
 * 表格工具类
 */
let DataGridUtils = {
    gridParam: {
        url: "",
        gridId: "table",
        height: $(window).height() - 310,
        searchForm: "searchForm", // 查询表单Id
        multipleFormSearch: false, //是否是多个搜索form
        isPagination: true,
        queryParamObj: {},//查询参数对象
        columns: [],
    },
    initGridByUrl: function (param) {
        var $table = param.gridId;
        var $searchForm = param.searchForm;
        $table = typeof ($table) === "string" ? $("#" + $table) : $($table);
        $searchForm = typeof ($searchForm) === "string" ? $("#" + $searchForm) : $($searchForm);
        if (param.multipleFormSearch) {
            if (typeof (param.gridId) == "string") {
                $searchForm = $("#" + param.gridId + "SearchForm")
            } else {
                $searchForm = $(param.gridId.selector + "SearchForm");
            }
        }
        param.gridId = $table.attr("id");
        $table.attr("bootstrap-table-instance", "bootstrap-table-instance");    //标记表格为已经实例化
        $table.data("$searchForm", $searchForm);                                //保存搜索表单jQuery元素;

        $table.bootstrapTable({
            //后台服务地址
            url: param.url,
            // method: 'post',
            //为每一行指定唯一的标识符
            uniqueId: param.uniqueId || "id",
            //指定主键列
            idField: param.idField || "id",
            //转义HTML字符串，替换 &, <, >, ", `, 和 ' 字符.
            escape: true,
            //当数据为 undefined 时显示的字符,默认为 '-'
            undefinedText: "-",
            //radio 和 checkBox 列 name
            selectItemName: param.selectItemName || "btSelectItem",
            //是否启用缓存
            cache: param.cache || false,
            //卡片模式
            cardView: false,
            //是否自定义列宽
            resizable: param.resizable || true,
            //传递格式
            dataType: "json",
            //设置为 true 在点击分页按钮或搜索按钮时，将记住checkbox的选择项
            maintainSelected: true,
            //服务端返回数据键值
            dataField: param.dataField || "data",
            //刷新事件
            silent: true,
            //加载消息提示
            formatLoadingMessage: function () {
                return "请稍等，正在加载中...";
            },
            //是否显示行间隔色
            striped: param.striped || true,
            //是否分页
            pagination: param.isPagination || false,
            //单页记录数
            pageSize: param.pageSize || 10,
            //分页步进值
            pageList: param.pageList || [10, 20, 50, 100],
            //服务端分页:server,客户端分页:client
            sidePagination: param.sidePagination || "server",
            //请求方式
            contentType: "application/x-www-form-urlencoded",
            //是否显示查询
            search: param.search || false,
            //查询框对齐方式
            searchAlign: param.searchAlign || "right",
            //分页对齐方式
            paginationDetailHAlign: param.paginationDetailHAlign || "right",
            //是否显示 切换试图（table/card）按钮
            showToggle: param.showToggle || false,
            //查询参数组织方式
            queryParamsType: "limit",
            //查询参数
            queryParams: function (params) {
                return Utils.urlEncodeByForm(param.isPagination, param.queryParamObj, $searchForm, params);
            },
            //回车搜索
            searchOnEnterKey: param.searchOnEnterKey || false,
            //是否显示刷新按钮
            showRefresh: param.showRefresh || false,
            //列选择按钮
            showColumns: param.showColumns || false,
            //按钮对齐方式
            buttonsAlign: param.buttonsAlign || "right",
            //指定工具栏
            toolbar: param.toolbar || "#toolbar",
            //工具栏对齐方式
            toolbarAlign: param.toolbarAlign || "left",
            //列
            columns: param.columns || [],
            //是否显示导出
            showExport: param.showExport || false,
            // 是否显示合计
            showFooter: param.showFooter || false,
            //设置true 将在点击行时，自动选择rediobox 和 checkbox
            clickToSelect: param.clickToSelect || true,
            //导出的文件格式
            //exportTypes: ['excel'],
            //数据导出模式：basic'：当前页数据导出; 'all'：所有数据导出; 'selected'：选中数据导出
            exportDataType: param.exportDataType || "selected",
            //列进行排序时触发
            onSort: function (name, order) {
                if (typeof (window["__onSort"]) === "function")
                    window["__onSort"](name, order);
                if (typeof (param["onSort"]) === "function")
                    param["onSort"](name, order);
                return false;
            },
            //单击row事件
            onClickRow: function (row, $element) {
                if (typeof (window["__onClickRow"]) === "function")
                    window["__onClickRow"](row, $element, param);
                if (typeof (param["onClickRow"]) === "function")
                    param["onClickRow"](row, $element, param);
                return false;
            },
            //双击row事件
            onDblClickRow: function (row, $element) {
                if (typeof (window["__onDblClickRow"]) === "function")
                    window["__onDblClickRow"](row, $element);
                if (typeof (param["onDblClickRow"]) === "function")
                    param["onDblClickRow"](row, $element);
            },
            //列表加载成功后:
            onLoadSuccess: function (data) {
                $table.bootstrapTable({
                    resizable: true
                });
                $table.addClass("table-nowrap");
                var isFirstCheck = true;
                if (param.isFirstCheck != undefined) isFirstCheck = param.isFirstCheck;
                if (isFirstCheck) {
                    var rows = $table.bootstrapTable('getData');
                    if (rows.length != 0) {
                        $table.bootstrapTable('check', 0);
                    }
                }
                if (!param.height && $table.outerHeight(true) > 0) {
                    param.height = DataGridUtils.getHeight($table);
                }
                if (param.height < 300) param.height = 'auto';
                $table.bootstrapTable('resetView', {"height": param.height});
                //td加title属性
                var cellIndex = parseInt($table.find("th").length);
                $table.find("tr td").each(function () {
                    if (this.cellIndex != cellIndex) {
                        $(this).attr("title", $(this).text());
                    }
                });
                // $(".fixed-table-container").css({"padding-bottom": "40px", "height": param.height - 80});
                // $table.css("margin-top", "-40px");
                //回调函数 默认选中第一行执行子查询
                if (typeof (window["__onLoadSuccess"]) == "function") {
                    window["__onLoadSuccess"](rows, param);
                }
                if (typeof (_afterRenderTable) == "function") {
                    _afterRenderTable(data, param);
                }

                // 工具栏form查询:如果有多个searchForm
                if (param.multipleFormSearch) {
                    if ($searchForm.length === 1) {
                        var _searchGridId = ""
                        if (typeof (param.gridId) == "string") {
                            _searchGridId = param.gridId;
                        } else if (typeof (param.gridId) == "object") {
                            _searchGridId = param.gridId.selector;
                        }
                        var _searchBtnId = _searchGridId + "SearchIcon";
                        var $searchBtn = "<button id='" + _searchBtnId + "' class='btn btn-default btn-sm' style='float: right' title='查询'><i class='fa fa-search'></i></button>";
                        var $toolbar = $("#" + param.toolbar) || $("#" + _searchGridId + 'toolbar') || $searchForm.prev('div');
                        if ($toolbar) {
                            if ($toolbar.find("#" + _searchBtnId).length === 0) {
                                $toolbar.append($searchBtn);
                                // 点击-显示查询栏
                                $("#" + _searchBtnId).on("click", function () {
                                    $(this).blur();
                                    $searchForm.slideDown(100);
                                    // 点击非查询栏区域关闭
                                    $(document).bind("click.tableSearch", function (e) {
                                        var evt = e || window.event
                                        if (e && e.stopPropagation) {
                                            evt.stopPropagation()
                                        } else {
                                            window.event.cancelBubble = true
                                        }
                                        var aim = e.srcElement || e.target
                                        if (!$.contains(document.getElementById(_searchGridId + "SearchForm"), aim) && !$.contains(document.getElementById(_searchBtnId), aim) && document.getElementById(_searchBtnId) !== aim) {
                                            $searchForm.slideUp(100)
                                            $(document).unbind("click.tableSearch")
                                        }
                                    })
                                });
                                // 取消-隐藏查询栏
                                $searchForm.find(".cancel-Btn").on("click", function () {
                                    $searchForm.slideUp(100)
                                    $(document).unbind("click.tableSearch")
                                });
                            }
                        }
                    }
                }
            },
            onLoadError: function () {
                //layer.close(timer);
            },
            //中文支持,
            locale: "zh-CN",
            //是否显示详情折叠
            detailView: param.detailView || false,
            //是否单选
            singleSelect: param.singleSelect || false,
            //详情格式化
            detailFormatter: function (index, row, element) {
                var html = '';
                $.each(row, function (key, val) {
                    html += "<p>" + key + ":" + val + "</p>"
                });
                return html;
            }
        });
    },
    refresh: function ($table) {
        var queryData = {}, param = {};
        if ($.isPlainObject($table)) {
            param = $table;
            $table = $("#" + (param.gridId || "table"));
            queryData = $("#" + (param.searchForm || "searchForm")).serialize();
        } else {
            $table = $($table);
            queryData = $table.data("$searchForm").serialize();
            param = $table.bootstrapTable("getOptions");
            //如果表格不可见就不执行刷新
            // if($table.filter(":hidden").length !== 0) return;
        }
        $table.bootstrapTable('refresh', {url: param.url, data: queryData});
    },
    getHeight: function ($table) {
        var height = 0;
        if ($table) {
            height = ($(window).height() - document.body.scrollHeight) + $table.parents('.bootstrap-table').outerHeight()
        } else {
            //设置高度
            var formHeight = $("#searchForm").height() || 0;
            var tabHeight = $(".nav").height() || 0;
            /*if(tabHeight > 0) tabHeight += 14;*/
            var titleHeight = 0;
            $.each($(".ibox-title"), function (index, obj) {
                titleHeight += $(obj).height() || 0;
            });
            titleHeight = titleHeight || 10;
            height = $(window).height() - formHeight - titleHeight - tabHeight - 65;
            height = height - ($("body").innerHeight() - $("body").height()) - 4;
        }
        return height > 500 ? 500 : (height < 200 ? 200 : height);
    },
    getSelectRows: function (gridId) {
        $table = typeof gridId === "string" ? $('#' + gridId) : $(gridId);
        return $table.bootstrapTable('getSelections');
    },

}


/**
 * ajax请求统一拦截
 **/
if (window.jQuery) {
    const unauthorizedCode = [401, 601, 602, 603]; // 登录失效状态码
    const token = getCookie(tokenKey);
    jQuery(document).bind("ajaxSend", function (event, request, settings) {
        if (settings.url) {
            var headers = settings.headers || {};
            headers[tokenKey] = token;
            settings.headers = headers;
            request.setRequestHeader(tokenKey, token);
        }
    }).bind("ajaxComplete", function (event, xhr, settings) {
        const responseJSON = xhr.responseJSON || xhr.responseText ? JSON.parse(xhr.responseText) : '';
        const responseCode = responseJSON.code;
        if (settings.url) {
            if (unauthorizedCode.indexOf(responseJSON.status) !== -1) {
                delCookie(tokenKey);
                let msgText = "即将跳转登录页面！";
                if (responseJSON.status === 401) {
                    msgText = "游客请登录！";
                } else if (responseJSON.status === 601) {
                    msgText = "不合法的token，请重新登录!"
                } else if (responseJSON.status === 602) {
                    msgText = "本账号在异地登录，本会话失效，请重新登录!"
                } else if (responseJSON.status === 603) {
                    msgText = "会话已超时失效，请重新登录!"
                }
                layer.msg(msgText, {icon: 0, time: 1500}, function () {
                    window.location.href = window.location.origin + "/views/html/login.html";
                })
            } else if (responseCode && responseCode !== 1) {//1-success
                layer.msg(responseJSON.data || '失败', {icon: 0, time: 1500})
            }
        }
    }).bind("ajaxError", function (event, XMLHttpRequest, ajaxOptions, thrownError) {
        layer.msg("后台异常，请联系管理员！" + thrownError, {icon: 2, time: 1500})
    })

}